/*
 * File:   Circle.h
 * Author: RedEyedKiller
 *
 * Created on 24 Μάρτιος 2010, 8:34 μμ
 */

#include "Mathematics.h"
#include "Rect.h"

namespace Math
{

// <editor-fold defaultstate="collapsed" desc="Constructors">

Rect::Rect(int top, int left, int height, int width)
{
    this->height = height;
    this->left = left;
    this->top = top;
    this->width = width;
}

Rect::Rect(float top, float left, float height, float width)
{
    this->height = static_cast<int> (height);
    this->left = static_cast<int> (left);
    this->top = static_cast<int> (top);
    this->width = static_cast<int> (width);
}

Rect::Rect(double top, double left, double height, double width)
{
    this->height = static_cast<int> (height);
    this->left = static_cast<int> (left);
    this->top = static_cast<int> (top);
    this->width = static_cast<int> (width);
}

Rect::Rect(const Rect& orig)
{
    this->height = static_cast<int> (orig.height);
    this->left = static_cast<int> (orig.left);
    this->top = static_cast<int> (orig.top);
    this->width = static_cast<int> (orig.width);
}

Rect& Rect::operator =(const Rect& orig)
{
    this->height = orig.height;
    this->left = orig.left;
    this->top = orig.top;
    this->width = orig.width;
    return *this;
}

Shape* Rect::Clone()
{
    return new Rect(*this);
}// </editor-fold>

// <editor-fold defaultstate="collapsed" desc="Setys & Getys">

void Rect::Set(int top, int left, int height, int width)
{
    this->height = height;
    this->left = left;
    this->top = top;
    this->width = width;
}

void Rect::Set(float top, float left, float height, float width)
{
    this->height = static_cast<int> (height);
    this->left = static_cast<int> (left);
    this->top = static_cast<int> (top);
    this->width = static_cast<int> (width);
}

void Rect::Set(double top, double left, double height, double width)
{
    this->height = static_cast<int> (height);
    this->left = static_cast<int> (left);
    this->top = static_cast<int> (top);
    this->width = static_cast<int> (width);
}// </editor-fold>

Vector2F Rect::GetCenter() const
{
    float y = height * 0.5 + top;
    float x = width * 0.5 + left;
    return Vector2F(x, y);
}

void Rect::SetCenter(const Vector2F& center)
{
    top = center.GetY() - height * 0.5;
    left = center.GetX() - width * 0.5;
}

Vector2I Rect::GetOrigin() const
{
    return Vector2I(left, top);
}

Vector2F Rect::GetDimensions()
{
    return Math::Vector2F(width,height);
}

void Rect::SetOrigin(const Vector2I& origin)
{
    top = origin.GetY();
    left = origin.GetX();
}

void Rect::SetOrigin(int x, int y)
{
    top = y;
    left = x;
}

void Rect::MoveOrigin(const Vector2I& origin)
{
    top += origin.GetY();
    left += origin.GetX();
}

void Rect::MoveOrigin(int x, int y)
{
    top += y;
    left += x;
}

// <editor-fold defaultstate="collapsed" desc="Distance from Closest Point">

Vector2F Rect::DistanceClosestPoint(const Shape& shape) const
{
    return shape.DistanceClosestPointFrom(*this);
}

Vector2F Rect::DistanceClosestPoint(const Vector2F& vect) const
{
    return Math::DistanceClosestPoint(*this, vect);
}// </editor-fold>

// <editor-fold defaultstate="collapsed" desc="Intersection proxy Methods">

bool Rect::Intersect(const Shape& shape) const
{
    return shape.IntersectWith(*this);
}

bool Rect::Intersect(const Vector2I& vec) const
{
    return Math::Intersect(*this, vec);
}

bool Rect::Intersect(const Vector2F& vec) const
{
    return Math::Intersect(*this, vec);
}


// </editor-fold>

// <editor-fold defaultstate="collapsed" desc="Intersection Ex Proxy Methods">

IntersectionType Rect::Intersect(const Shape& shape, Vector2Templ<float>& axisInfo) const
{
    return shape.IntersectWith(*this, axisInfo);
}// </editor-fold>

float Rect::CalculateArea() const
{
    return height * width;
}

// <editor-fold defaultstate="collapsed" desc="Proxy methods for double dispatch">

bool Rect::IntersectWith(const Circle& circle) const
{
    return Math::Intersect(circle, *this);
}

bool Rect::IntersectWith(const Rect& rect) const
{
    return Math::Intersect(rect, *this);
}

IntersectionType Rect::IntersectWith(const Circle& circle, Vector2Templ<float>& axisInfo) const
{
    return Math::Intersect(circle, *this, axisInfo);
}

IntersectionType Rect::IntersectWith(const Rect& rect, Vector2Templ<float>& axisInfo) const
{
    return Math::Intersect(rect, *this, axisInfo);
}

Vector2F Rect::DistanceClosestPointFrom(const Rect& rect) const
{
    return Math::DistanceClosestPoint(rect, *this);
}

Vector2F Rect::DistanceClosestPointFrom(const Circle& circle) const
{
    return Math::DistanceClosestPoint(circle, *this);
}// </editor-fold>

}
